package org.wheel.plugins.toolkit.util.sql.expander;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import lombok.Getter;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
import net.sf.jsqlparser.expression.operators.relational.*;

import java.util.*;

/**
 * 在 AST 里寻找“OR-AND 字典序”模式，替换成 RowComparisonExpr
 * 支持 2~N 列，支持 > >= < <= = <>
 */
@Getter
public class RowReverseVisitor extends ExpressionVisitorAdapter<Void> {

    // 直接使用 LogFactory 创建日志对象，Hutool 会自动检测项目中的日志框架（优先级：Slf4j > Log4j > Logback > JDK Logging）
    private static final Log log = LogFactory.get();
    /**
     * 如果识别成功，这里保存新生成的 RowComparisonExpr，
     * 供外层把原表达式整体替换掉。
     */
    private RowComparisonExpr replaced;

    private OrExpression orExpression;

    /**
     * 是否匹配上，默认 false
     */
    private boolean match;

    /* 唯一入口：处理最外层 OR */
    @Override
    public <S> Void visit(OrExpression orExpr, S context) {
        this.orExpression = orExpr;
        List<AndExpression> ands = flattenOr(orExpr);
        if (ands.isEmpty()) {
            return null;
        }

        tryReverse(ands).ifPresent(row-> {
            match = true;
            this.replaced = row;
        });

        return null;
    }



    /* ------------------------------------------------------------------
     * 把 A OR B OR C … 拆成 List<AndExpression>
     * ------------------------------------------------------------------ */
    /**
     * 把 OR 表达式拆成 List<AndExpression>：
     * 1. AndExpression 直接加入
     * 2. ComparisonOperator 包成单元素 AndExpression
     * 3. 其他类型立即返回 null（快速失败）
     */
    private List<AndExpression> flattenOr(Expression expr) {
        List<AndExpression> list = new ArrayList<>();
        if (expr instanceof OrExpression) {
            OrExpression or = (OrExpression) expr;
            List<AndExpression> left = flattenOr(or.getLeftExpression());
            List<AndExpression> right = flattenOr(or.getRightExpression());
            list.addAll(left);
            list.addAll(right);
        } else if (expr instanceof AndExpression) {
            list.add((AndExpression) expr);
        } else if (expr instanceof ComparisonOperator) {
            // 单比较 -> 包成 AndExpression
            list.add(new AndExpression(expr, expr));
        } else if(expr instanceof ParenthesedExpressionList<?> expList) {
//            list.addAll(expList.stream()
//                    .map(item->(AndExpression)flattenOr(item))
//                    .toList());
            expList.forEach(item->{
                list.addAll(flattenOr((Expression)item));
            });
        } else {
            return Collections.emptyList(); // 无法识别
        }
        return list;
    }

    /* ------------------------------------------------------------------
     * 核心：判断 AND 列表是否符合字典序展开
     * ------------------------------------------------------------------ */
    private Optional<RowComparisonExpr> tryReverse(List<AndExpression> ands) {
        if(CollectionUtil.isEmpty(ands)){
            return Optional.empty();
        }
//        int n = ands.size();
//        /* 1 收集每一层的最末比较 (li op ri) 与前面所有等式 */
//        List<List<Comparison>> tiers = new ArrayList<>(n);
//        for (AndExpression and : ands) {
//            List<Comparison> cmps = flattenAnd(and);
//            if (cmps == null || cmps.size() > n) return Optional.empty();
//            tiers.add(cmps);
//        }
//        /* 2 列数 = 最长 tier 长度 */
//        int colCount = tiers.stream().mapToInt(List::size).max().orElse(0);
//        if (colCount != n) return Optional.empty(); // 必须是三角形
//
//        /* 3 检查顺序、运算符、同一列/同一参数 */
//        String lastOp = "";
//        List<Expression> leftCols  = new ArrayList<>();
//        List<Expression> rightPars = new ArrayList<>();
//
//        for (int i = 0; i < colCount; i++) {
//            List<Comparison> tier = tiers.get(i);
//            if (tier.size() != i + 1) return Optional.empty();
//
//            Comparison lastInTier = tier.get(i);
//            String expectOp = (i == colCount - 1) ? lastInTier.op : "=";
//            if (!expectOp.equals(lastInTier.op)) return Optional.empty();
//
//            if (i == 0) {          // 初始化
//                lastOp = lastInTier.op;
//            }
//            // 所有 tier 必须共享同一组列/参数
//            for (Comparison c : tier) {
//                if (!c.left.equals(tier.get(0).left) || !c.right.equals(tier.get(0).right))
//                    return Optional.empty();
//            }
//            leftCols.add(tier.get(0).left);
//            rightPars.add(tier.get(0).right);
//        }

        /* 1. 收集所有简单比较 (li op ri) 与等式 (li = ri) */
        List<List<Comparison>> tiers = new ArrayList<>();
        for (int i = 0; i < ands.size(); i++) {
            List<Comparison> cmps = flattenAnd(ands.get(i));
            if(CollectionUtil.isNotEmpty(cmps)){
              tiers.add(cmps);
            }
        }

        /* 2. 检查列/参数顺序、运算符是否符合规则 */
        if(CollectionUtil.isEmpty(tiers)){
            return Optional.empty();
        }
        List<Comparison> lastTiers = tiers.get(tiers.size() - 1);
        if(CollectionUtil.isEmpty(lastTiers)){
            return Optional.empty();
        }
        String lastOp = lastTiers.get(lastTiers.size() - 1).op; // 最后一列运算符
        List<Expression> leftCols  = new ArrayList<>();
        List<Expression> rightPars = new ArrayList<>();

        for (int i = 0; i < tiers.size(); i++) {
            List<Comparison> tier = tiers.get(i);
            Comparison cp = tier.get(tier.size()-1);
            leftCols.add(cp.left);
            rightPars.add(cp.right);
        }
        return Optional.of(new RowComparisonExpr(leftCols, lastOp, rightPars));
    }

    /* 把一个 AND 表达式拆成 (l0=r0)∧(l1=r1)∧…∧(lk op rk) */
    private List<Comparison> flattenAnd(Expression expr) {
        List<Comparison> list = new ArrayList<>();
        if (expr instanceof AndExpression) {
            AndExpression and = (AndExpression) expr;
            list.addAll(flattenAnd(and.getLeftExpression()));
            list.addAll(flattenAnd(and.getRightExpression()));
        } else if (expr instanceof ComparisonOperator) {
            ComparisonOperator cmp = (ComparisonOperator) expr;
            if (cmp instanceof EqualsTo || cmp instanceof GreaterThan || cmp instanceof GreaterThanEquals
                    || cmp instanceof MinorThan || cmp instanceof MinorThanEquals || cmp instanceof NotEqualsTo) {
                list.add(new Comparison(cmp.getLeftExpression(), cmp.getRightExpression(), cmp.getStringExpression()));
            } else {
                return Collections.emptyList(); // 不支持的比较
            }
        } else if (expr instanceof ParenthesedExpressionList<?> pe) {
            return pe.stream().flatMap(item->flattenAnd(item).stream()).toList();
        } else {
            return Collections.emptyList(); // 不是简单比较
        }
        return list;
    }

    /* 简单内部结构：保存一次 li op ri */
    private record Comparison (Expression left, Expression right, String op){

    }
}